﻿//-----------------------------------------------------------------------
// <copyright file="SQLDbAction.cs" >
//     All rights reserved.
//     THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//     KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//     IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//     PARTICULAR PURPOSE.
// </copyright>
// <author>Marais van Zyl</author>
// <email>marais@projexis.co.za</email>
// <CreatedDate>2010/01/26</CreatedDate>
//-----------------------------------------------------------------------
namespace Accountability4net.MSSQLDbProvider
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// Defines an action that represents the details of a transaction on an account
    /// </summary>
    public class SQLDbAction : BaseAction
    {
        /// <summary>
        /// the id of the action
        /// </summary>
        private long id_;

        /// <summary>
        /// the provider being used
        /// </summary>
        private SQLDbProvider provider_;

        /// <summary>
        /// Initializes a new instance of the SQLDbAction class
        /// </summary>
        /// <param name="provider">the provider being used to create the action</param>
        /// <param name="type">the <see cref="ActionType"/> of the action</param>
        /// <param name="account">the account of the action</param>
        /// <param name="amount">the amount of the action</param>
        public SQLDbAction(SQLDbProvider provider, ActionType type, IAccount account, decimal amount)
            : base(type, account, amount)
        {
            this.provider_ = provider;
        }

        /// <summary>
        /// Gets the Id of the Action
        /// </summary>
        public long Id
        {
            get
            {
                return this.id_;
            }
        }

        /// <summary>
        /// Gets or sets the id of the transaction this action belongs to
        /// </summary>
        public Guid TransactionId
        {
            get;
            set;
        }

        /// <summary>
        /// Creates a new SQLDBAction
        /// </summary>
        /// <param name="provider">the provider being used to create the action</param>
        /// <param name="type">the <see cref="ActionType"/> of the action</param>
        /// <param name="account">the account the action uses</param>
        /// <param name="amount">the amount of the transaction</param>
        /// <returns>the newly created action</returns>
        public static SQLDbAction Create(SQLDbProvider provider, ActionType type, IAccount account, decimal amount)
        {
            var action = new SQLDbAction(provider, type, account, amount);
            string sql = "INSERT INTO [AccountAction] ([type], [account_id], [amount]) VALUES (@type, @accountId, @amount); SELECT SCOPE_IDENTITY();";
            using (var command = provider.CreateCommand(sql))
            {
                command.Parameters.AddWithValue("@type", type);
                command.Parameters.AddWithValue("@accountId", account.Number);
                command.Parameters.AddWithValue("@amount", amount);
                action.id_ = Convert.ToInt64(command.ExecuteScalar());
            }

            return action;
        }

        /// <summary>
        /// Gets all the actions for an account
        /// </summary>
        /// <param name="provider">the provider being used.</param>
        /// <param name="account">the account's actions that must be searched for</param>
        /// <param name="transaction">the transaction the action should belong to</param>
        /// <returns>the actions found</returns>
        public static IEnumerable<IAction> Retrieve(SQLDbProvider provider, IAccount account, ITransaction transaction)
        {
            string sql = "SELECT * FROM [AccountAction] WITH (nolock) WHERE [Account_id] = @accountId AND [Transaction_id] = @transactionId";
            using (var command = provider.CreateCommand(sql))
            {
                command.Parameters.AddWithValue("@accountId", account.Number);
                command.Parameters.AddWithValue("@transactionId", transaction.ID);
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var type = (ActionType)Enum.ToObject(typeof(ActionType), reader.GetByte(2));
                        var amount = reader.GetDecimal(3);
                        var action = new SQLDbAction(provider, type, account, amount);
                        action.id_ = reader.GetInt64(0);
                        yield return action;
                    }
                }
            }
        }

        /// <summary>
        /// Impliments the PropertyChanged event of the class
        /// </summary>
        public void WirePropertyChanged()
        {
        }
    }
}
